#include "thread_cache.h"
#include "central_cache.h"

// 向下一层（CentralCache）申请内存
void* ThreadCache::FetchFromCentralCache(size_t index, size_t size)
{
    // 慢开始反馈调节算法
    size_t batchNum = MIN(SizeClass::NumMoveSize(size), _FreeList[index].Maxsize());
    if (batchNum == _FreeList[index].Maxsize())
    {
        _FreeList[index].Maxsize() += 1;
    }

    void* start = nullptr;
    void* end = nullptr;
    //LOG(DEBUG, "进入CentralCache层\n");
    size_t actualNum = CentralCache::GetInstance()->FetRangeObj(start, end, batchNum, size);
    //LOG(DEBUG, "actualNum: %d\n", actualNum);
    assert(actualNum > 0);

    if (batchNum == 1)
    {
        assert(start == end);
        return start;
    }
    else
    {
        _FreeList[index].PushRang(Nextobj(start), end, actualNum - 1);
        return start;
    }
}

// 内存申请
void* ThreadCache::Allocate(size_t size)
{
    assert(size <= MAX_BYTES);
    size_t alignSize = SizeClass::RoundUp(size);
    size_t index = SizeClass::Index(size);
    //LOG(DEBUG, "alignSize: %d, index: %d\n", alignSize, index);

    if (!_FreeList[index].Empty())
    {
        return _FreeList[index].Pop();
    }
    else
    {
        //LOG(DEBUG, "ThreadCache 中没有多余内存, 向下一层申请\n");
        return FetchFromCentralCache(index, alignSize);
    }
}

// 内存释放
void ThreadCache::Deallocate(void* ptr, size_t size)
{
    assert(ptr);
    assert(size <= MAX_BYTES);
    size_t index = SizeClass::Index(size);
    _FreeList[index].Push(ptr);

    // 如果对应的链表长度过长，就还一部分给CentralCache
    if (_FreeList[index].Size() >= _FreeList[index].Maxsize())
    {
        //LOG(DEBUG, "链表过长, 释放部分节点还给CentralCache\n");
        ListTooLong(_FreeList[index], size);
    }
}

// 将过多的内存还给CentralCache
void ThreadCache::ListTooLong(FreeList& list, size_t size)
{
    void* start = nullptr;
    void* end = nullptr;
    list.PopRang(start, end, list.Maxsize());

    //LOG(DEBUG, "将多余的内存还回CentralCache\n");
    CentralCache::GetInstance()->ReleaseListToSpans(start, size);
}